﻿//#r "Microsoft.Xna.Framework.dll"

module XNAExtensions

    open System
    open Microsoft.Xna.Framework
    open Microsoft.Xna.Framework.Graphics  

    type Random
      with
        member this.NextFloat v =
          let d = this.NextDouble() |> float32
          in d * v * 0.5f + v

    type Vector3
      with
        member this.ForwardCube 
          with get() = 
            let ax,ay,az = abs this.X, abs this.Y, abs this.Z
            in this.Z > 0.0f && az > ay && az > ax
        member this.BackwardCube 
          with get() = 
            let ax,ay,az = abs this.X, abs this.Y, abs this.Z
            in this.Z < 0.0f && az > ay && az > ax
        member this.RightCube
          with get() = 
            let ax,ay,az = abs this.X, abs this.Y, abs this.Z
            in this.X > 0.0f && ax > ay && ax > az
        member this.LeftCube 
          with get() = 
            let ax,ay,az = abs this.X, abs this.Y, abs this.Z
            in this.X < 0.0f && ax > ay && ax > az
        member this.TopCube 
          with get() = 
            let ax,ay,az = abs this.X, abs this.Y, abs this.Z
            in this.Y > 0.0f && ay > ax && ay > az
        member this.BottomCube 
          with get() = 
            let ax,ay,az = abs this.X, abs this.Y, abs this.Z
            in this.Y < 0.0f && ay > ax && ay > az

    let transpose_cube (face:CubeMapFace) (p:Vector3) =
        match face with
        | CubeMapFace.PositiveZ -> Vector3(p.X, p.Y, p.Z)
        | CubeMapFace.NegativeZ -> Vector3(1.0f-p.X, p.Y, 1.0f-p.Z)
        | CubeMapFace.PositiveX -> Vector3(1.0f-p.Z, p.Y, p.X)
        | CubeMapFace.NegativeX -> Vector3(p.Z, p.Y, 1.0f-p.X)
        | CubeMapFace.PositiveY -> Vector3(p.X, 1.0f-p.Z, p.Y)
        | CubeMapFace.NegativeY -> Vector3(p.X, p.Z, 1.0f-p.Y)
        | _ -> p

    type BoundingBox
      with
        member this.ScaleToUnit (p:Vector3) =
          let scale v min max = (v-min) / (max-min)
          in Vector3(scale p.X this.Min.X this.Max.X,
                     scale p.Y this.Min.Y this.Max.Y,
                     scale p.Z this.Min.Z this.Max.Z)

    let pow (x:float32) (y:float32) = Math.Pow(x|>float,y|>float) |> float32